package com.xyyl.patient.controller;

import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.Executors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayBaseRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayBaseResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.collect.Maps;
import com.xyyl.patient.common.utils.SysConfigUtils;
import com.xyyl.patient.core.constant.AppEnum;
import com.xyyl.patient.core.controller.BaseController;
import com.xyyl.patient.core.util.DateUtils;
import com.xyyl.patient.core.util.ResponseBodyResult;
import com.xyyl.patient.core.util.RestClient;
import com.xyyl.patient.core.util.StringUtils;
import com.xyyl.patient.entity.order.ConsultOrder;
import com.xyyl.patient.service.doctor.DoctorService;
import com.xyyl.patient.service.order.ConsultOrderService;
import com.xyyl.patient.service.user.UserService;
import com.xyyl.patient.vo.user.UserVo;

/**
 * @projectName:xyyl-patient-web
 * @ClassName: TextOrderPayController
 * @Description: 图文咨询订单Controller
 * @author chens
 * @date 2017年8月22日
 */
@RestController
@RequestMapping("/consultOrderPay")
public class ConsultOrderController extends BaseController {

	private Logger logger = LogManager.getLogger(ConsultOrderController.class);

	@Autowired
	private ConsultOrderService consultOrderService;

	@Autowired
	private UserService userService;

	@Autowired
	private WxPayService payService;

	@Autowired
	private DoctorService doctorService;

	@Value("#{weixin['common.domain']}")
	private String domain;

	/**
	 * @Title: submitOrder
	 * @Description: 提交订单
	 * @param @param consultOrder
	 * @param @return    参数
	 * @return JSONObject    返回类型
	 * @throws
	 */
	@RequestMapping(value = "/submitOrder", method = RequestMethod.POST)
	@ResponseBody
	public JSONObject submitOrder(@RequestBody ConsultOrder consultOrder) {

		logger.info("---submit  payOrder---");

		try {

			if (consultOrder != null) {
				/** 如果订单金额为0，即免费咨询，则默认已支付 **/
				BigDecimal orderAmount = consultOrder.getPayamount().setScale(2);
				if (orderAmount.doubleValue() == 0.00) {
					consultOrder.setPaytype(AppEnum.common.Order_payType_account.getValue());
					consultOrder.setStatus(AppEnum.common.Pay_status_confirm.getValue());
				} else {
					consultOrder.setPaytype(AppEnum.common.Pay_status_not.getValue());
					consultOrder.setStatus(AppEnum.common.Pay_status_not.getValue());
				}
			}
			return ResponseBodyResult.success("下单成功", consultOrderService.insertConsultOrder(consultOrder));

		} catch (Exception e) {
			return ResponseBodyResult.error("下单失败", e);
		}
	}

	/**
	 * @Title: queryOrderDetailById
	 * @Description:订单明细查询
	 * @param @param id
	 * @param @return    参数
	 * @return JSONObject    返回类型
	 * @throws
	 */
	@RequestMapping(value = "/queryOrderDetailById", method = RequestMethod.GET)
	public JSONObject queryOrderDetailById(@RequestParam Integer id) {

		logger.info(" query order:{}", id);
		try {
			ConsultOrder consultOrder = consultOrderService.queryOrderDetailById(id);
			if (consultOrder != null) {
				String questionBody = consultOrder.getQuestionbody();
				if (questionBody.length() > 8) {
					questionBody = consultOrder.getQuestionbody().substring(0, 8) + "...";
					consultOrder.setQuestionbody(questionBody);
				}

			}
			return ResponseBodyResult.success(consultOrder);
		} catch (Exception e) {
			return ResponseBodyResult.error("订单明细查询失败!", e);
		}
	}

	/**
	 * @Title: confirmPay
	 * @Description: 确认支付 
	 * 一、余额支付： 1.直接扣款即可，并更新订单
	 * 二、微信支付：1.调用微信统一下单接口，返回JSSDKPayInfo相关的信息
	 * @param @param consultOrder
	 * @param @return    参数
	 * @return JSONObject    返回类型
	 * @throws
	 */
	@RequestMapping(value = "/confirmPay", method = RequestMethod.POST)
	public JSONObject confirmPay(@RequestBody ConsultOrder consultOrder) {

		logger.info("---confirmPay  payOrder---");

		Integer payType = consultOrder.getPaytype();
		BigDecimal orderAmout = consultOrder.getPayamount();
		try {
			ConsultOrder consultOrderVo = consultOrderService.queryOrderDetailById(consultOrder.getId());

			/** 查询账户信息 **/
			UserVo userVo = userService.queryUserDetailById(consultOrder.getUserid());
			BigDecimal totalFee = userVo.getAccountbalance();

			if (consultOrderVo.getStatus().equals(AppEnum.common.Pay_status_confirm.getValue())) {
				return ResponseBodyResult.fail("该订单已支付，请勿重复提交!");
			}

			if (payType.equals(AppEnum.common.Order_payType_account.getValue())) {
				if (totalFee.doubleValue() <= 0.00) {
					return ResponseBodyResult.fail("支付失败!,账户余额不足!");
				} else {
					consultOrder.setBalanceAmount(orderAmout);
					consultOrderService.updateConsultOrder(consultOrder);
					
					//发送短信通知
					sendSystemSMS(consultOrderVo.getDoctorid());
					
					return ResponseBodyResult.success("支付成功!", "SUCCESS");
				}

			} else {
				if (consultOrder.getPlatformAmount() == null) {
					BigDecimal platformAmount = new BigDecimal("0.01");
					/** 如果订单金额大于账户余额， 则微信支付金额=订单金额-账户余额，否则全部微信支付 **/
					if (orderAmout.compareTo(totalFee) > 0) {
						platformAmount = orderAmout.subtract(totalFee);
					} else {
						platformAmount = orderAmout;
					}
					consultOrder.setPlatformAmount(platformAmount);
				}
				return submitWxPay(consultOrder);
			}

		} catch (Exception e) {

			return ResponseBodyResult.error("订单提交失败!", e);
		}
	}

	/**
	 * @Title: submitWxPay
	 * @Description:提交微信统一下单
	 * @param @param consultOrder
	 * @param @return    参数
	 * @return JSONObject    返回类型
	 * @throws
	 */
	private JSONObject submitWxPay(ConsultOrder consultOrder) {
		/** 组装参数信息 **/
		WxPayUnifiedOrderRequest prepayInfo = WxPayUnifiedOrderRequest.newBuilder().openid(consultOrder.getOpenid())
				.outTradeNo(consultOrder.getOrdersn())
				.totalFee(WxPayBaseRequest.yuanToFee(String.valueOf(consultOrder.getPlatformAmount())))
				.body(consultOrder.getOrderDetail()).spbillCreateIp("192.168.0.1")
				.notifyURL(domain + "/consultOrderPay/orderPayCallback").build();

		/** 提交微信统一下单 **/
		Map<String, String> payInfos = Maps.newHashMap();
		try {
			payInfos = this.payService.getPayInfo(prepayInfo);
			if (payInfos != null && payInfos.get("package") != null) {
				return ResponseBodyResult.success("提交成功", payInfos);
			} else {
				return ResponseBodyResult.fail("统一下单失败");
			}
		} catch (WxPayException e) {
			return ResponseBodyResult.error("统一下单失败", e);
		}

	}

	/**
	 * @Title: orderPayCallback
	 * @Description: 微信通知支付结果的回调并更新订单信息
	 * @param
	 * @param
	 * @return String 返回类型 @throws
	 */
	@RequestMapping(value = "/orderPayCallback", method = RequestMethod.POST)
	public String orderPayCallback(HttpServletRequest request, HttpServletResponse response) {

		logger.info("---callback  payOrder---");

		try {
			synchronized (this) {
				/** 解析支付结果 **/
				String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
				WxPayOrderNotifyResult result = payService.parseOrderNotifyResult(xmlResult);
				if (AppEnum.common.Pay_result_success.getName().equals(result.getReturnCode())) {
					if (AppEnum.common.Pay_result_success.getName().equals(result.getResultCode())) {
						
						logger.debug("微信回调状态：["+result.getReturnCode()+"]");
						/** 支付成功，处理业务数据 **/
						String orderId = result.getOutTradeNo();
						String transactionId = result.getTransactionId();
						String openid = result.getOpenid();
						ConsultOrder consultOrder = consultOrderService.queryOrderDetailBySn(openid, orderId);
						if (consultOrder.getStatus().equals(AppEnum.common.Pay_status_not.getValue())) {
							consultOrder.setStatus(AppEnum.common.Pay_status_confirm.getValue());
							consultOrder.setPayordersn(transactionId);
							consultOrder.setPaytype(AppEnum.common.Order_payType_wx.getValue());
							String totalFee = WxPayBaseResult.feeToYuan(result.getTotalFee());
							consultOrder.setPlatformAmount(new BigDecimal(totalFee).setScale(2));
							consultOrderService.updateConsultOrder(consultOrder);
							
							//发送短信通知
							sendSystemSMS(consultOrder.getDoctorid());
						}
						
						return WxPayNotifyResponse.success("OK");
					} else {
						return WxPayNotifyResponse.fail("result_code is FAIL");
					}
				} else {
					return WxPayNotifyResponse.fail("check signature FAIL");
				}

			}
		} catch (Exception e) {
			return WxPayNotifyResponse.fail("http request FAIL");
		}

	}

	/**
	 * @Title: queryUnfinishedOrderByUid
	 * @Description: 查询未完成订单
	 * @param @param userid
	 * @param @param doctorid
	 * @param @return    参数
	 * @return JSONObject    返回类型
	 * @throws
	 */
	@RequestMapping(value = "/queryUnfinishedOrderByUid", method = RequestMethod.GET)
	public JSONObject queryUnfinishedOrderByUid(@RequestParam Integer userid, Integer doctorid) {

		logger.info(" queryUnfinishedOrderByUid:{}", userid);
		try {
			return ResponseBodyResult.success(consultOrderService.queryUnfinishedOrderByUid(userid, doctorid));
		} catch (Exception e) {
			return ResponseBodyResult.error("订单明细查询失败!", e);
		}
	}

	/**
	 * @Title: confirmFinishOrder
	 * @Description:订单完成确认
	 * 1.患者端咨询完成后，若医生端未立即结束订单，则将该订单置为已锁定【status:4】；
	 * 2.锁定的订单由医生端自行处理，将状态置为已完成【stauts:3】
	 * @param @param consultOrder
	 * @param @return    参数
	 * @return JSONObject    返回类型
	 * @throws
	 */
	@RequestMapping(value = "/confirmFinishOrder", method = RequestMethod.POST)
	public JSONObject confirmFinishOrder(@RequestBody ConsultOrder consultOrder) {
		logger.info(" confirmFinishOrder:{}", consultOrder.getId());
		try {
			if (consultOrder.getOrderType() == 2) {
				consultOrder.setStatus(AppEnum.common.Prder_status_lock.getValue());
			} else {
				consultOrder.setStatus(AppEnum.common.Order_status_cancel.getValue());
			}

			consultOrder.setUpdatetime(DateUtils.currentDatetime());
			return ResponseBodyResult.success(consultOrderService.confirmFinishOrder(consultOrder));
		} catch (Exception e) {
			return ResponseBodyResult.error("订单确认失败!", e);
		}
	}

	/**
	 * @Title: queryLastArchivesidByUserid
	 * @Description:返回最后一次档案ID
	 * @param @param userid
	 * @param @param type
	 * @param @return    参数
	 * @return JSONObject    返回类型
	 * @throws
	 */
	@RequestMapping(value = "/queryLastArchivesidByUserid", method = RequestMethod.GET)
	public JSONObject queryLastArchivesidByUserid(@RequestParam Integer userid, @RequestParam Integer type) {

		logger.info(" queryLastArchivesidByUserid:{}", userid);
		try {
			return ResponseBodyResult.success(consultOrderService.queryLastArchivesInfoByUserid(userid, type));
		} catch (Exception e) {
			return ResponseBodyResult.error("获取档案id失败!", e);
		}
	}

    /**
     * @Title: sendSystemSMS
     * @Description: 发送短信通知
     * @param  doctorid    参数
     * @return void    返回类型
     * @throws
     */
	public void sendSystemSMS(Integer doctorid) {

		logger.info("--- send message---");
		Executors.newSingleThreadExecutor().execute(new Runnable() {
			@Override
			public void run() {
				try {
					String mobile = doctorService.queryDoctorMoblieById(doctorid);
					if (StringUtils.isEmpty(mobile)) {
						logger.error("发送失败,手机号码不能为空!");
					}
					String sms_api_url = SysConfigUtils.getConfigValue(AppEnum.sysConfig.OMS_SYSTEM_SMS_API_URL.name());
					Map<String, Object> paramMap = Maps.newHashMap();
					paramMap.put("mobile", mobile);
					paramMap.put("smsTemplateKey", AppEnum.smsTemplaeKeys.SMS_TEMPLATE_CONSULT_ORDER.name());
					RestClient.postForObject(sms_api_url, JSON.toJSONString(paramMap), String.class);

				} catch (Exception e) {
					logger.error("发送失败:" + e);
				}

			}
		});
	}

}
